﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SvnCrowdConverter
{
    internal class SvnLocationFactory
    {
        private readonly IIoAdapter ioAdapter;

        internal SvnLocationFactory(IIoAdapter ioAdapter)
        {
            this.ioAdapter = ioAdapter;
        }

        public SvnLocation Create(string content)
        {
            var svnLocation = new SvnLocation(GetRepo(content), GetGroups(content));

            if (string.IsNullOrEmpty(svnLocation.Repo))
            {
                throw new ArgumentException(string.Format("repo is missing with content : {0}", content));
            }

            if (!svnLocation.Groups.Any())
            {
                throw new ArgumentException(string.Format("missing groups for repo {0} with content {1}", svnLocation.Repo, content));
            }

            return svnLocation;
        }

        private static string GetRepo(string content)
        {
            return ExtractContent(content, @"^\s*<\s*Location\s*/[^/]*/(?<Repo>[^>]*)\s*>", "Repo");
        }

        private IEnumerable<string> GetGroups(string content)
        {
            var groups = ToGroups(ExtractContent(content, @"^\s*PerlSetVar\s*CrowdAllowedGroups\s*(?<Groups>.*)", "Groups")).ToList();

            return groups.Any() ? groups : FileToGroups(ExtractContent(content, @"^\s*PerlSetVar\s*CrowdAuthzSVNAccessFile\s*(?<GroupsFile>.*)", "GroupsFile"));
        }

        private IEnumerable<string> FileToGroups(string filePath)
        {
            var content = ioAdapter.ReadAllText(filePath);

            var regex = new Regex(@"^@(?<Group>[^=]*)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Multiline);

            foreach (Match match in regex.Matches(content))
            {
                yield return match.Groups["Group"].Value.Trim();
            }
        }

        private static IEnumerable<string> ToGroups(string groups)
        {
            return groups.ToLower().Split(',').Where(x => !x.IsNullOrWhiteSpace()).ToList();
        }

        private static string ExtractContent(string content, string regexString, string groupname)
        {
            var regex = new Regex(regexString,
                RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Multiline);

            var extractContent = regex.Match(content).Groups[groupname].Value.Trim();
            return extractContent;
        }

    }
}